package com.xbongbong.sys.help;

import com.alibaba.fastjson.JSON;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.ComboTypeEnum;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.bi.ChartSourceEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.pojo.ProcessFieldAttrPojo;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.PackageConstant;
import com.xbongbong.pro.domain.entity.ext.ChartEntityEtx;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.SystemFieldFormulaEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.packages.enums.FeaturesEnum;
import com.xbongbong.pro.enums.packages.enums.PackageVersionEnum;
import com.xbongbong.pro.enums.vip.enums.VipJxcSaasMenuEnum;
import com.xbongbong.pro.enums.vip.enums.VipSaasMenuEnum;
import com.xbongbong.pro.packageInfo.pojo.vo.BasePackageInfoVO;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.FeeCompanyModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 套餐帮助类
 * @author 吴峰
 * @date 2020/08/12 19:21
 */
@Component
public class PackageHelp {

    @Resource
    private PackageWhitelistHelp packageWhitelistHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private FeeCompanyModel feeCompanyModel;

    /**
     * 表单设计中，标准版本隐藏复杂字段
     * @param featureList
     * @param entity
     * @return true: 有复杂字段；false：没有复杂字段
     */
    public void explainDesignHide(List<String> featureList, FieldAttrEntity entity) {
        Integer fieldType = entity.getFieldType();
        List<Integer> complexFieldType = FieldTypeEnum.getComplexList();
        // TODO bug-id：35450 因为先保存了，然后后续再获取就无法再显示
        if (Objects.equals(FieldTypeEnum.TEXT.getType(), entity.getFieldType()) && Objects.equals(1, entity.getIsRedundant())) {
            entity.setEditHide(0);
        }
        if (!FieldTypeEnum.getUltimateList().contains(fieldType)) {
            // 非旗舰版字段，直接返回
            return;
        }
        if (featureList.contains(FeaturesEnum.COMPLEX.getAlias()) && Objects.equals(1, entity.getIsRedundant())) {
            entity.setEditHide(0);
        } else if (!featureList.contains(FeaturesEnum.COMPLEX.getAlias()) && Objects.equals(1, entity.getIsRedundant())) {
            //
            entity.setEditHide(1);
        }
        if (!featureList.contains(FeaturesEnum.ULTIMATE.getAlias()) && FieldTypeEnum.getUltimatePrivateList().contains(fieldType) && Objects.equals(1, entity.getIsRedundant())) {
            // 非旗舰版，表单设计，隐藏阶段推进器字段；
            entity.setEditHide(1);
        }
    }

    /**
     * 新建、编辑、详情、列表，标准版本隐藏复杂字段
     * @param featureList
     * @param entity
     * @return true: 有复杂字段；false：没有复杂字段
     */
    public void explainHide(List<String> featureList, FieldAttrEntity entity) {
        Integer fieldType = entity.getFieldType();
        if (!FieldTypeEnum.getUltimateList().contains(fieldType)) {
            // 非旗舰版字段，直接返回
            return;
        }
        boolean a = !featureList.contains(FeaturesEnum.COMPLEX.getAlias()) || !featureList.contains(FeaturesEnum.ULTIMATE.getAlias());
        if (!featureList.contains(FeaturesEnum.COMPLEX.getAlias()) && Objects.equals(1, entity.getIsRedundant())) {
            entity.setVisible(0);
        } else if (!featureList.contains(FeaturesEnum.ULTIMATE.getAlias()) && FieldTypeEnum.getUltimatePrivateList().contains(fieldType) && Objects.equals(1, entity.getIsRedundant())) {
            // 非旗舰版，新建、编辑、详情、列表，隐藏阶段推进器字段；
            entity.setVisible(0);
        }
    }

    public Integer processHide(List<String> featureList, ProcessFieldAttrPojo entity) {
        Integer fieldType = entity.getFieldType();
        List<Integer> complexFieldType = FieldTypeEnum.getComplexList();
        if (!complexFieldType.contains(fieldType)) {
            // 非复杂字段，直接返回
            return 2;
        }
        if (featureList.contains(FeaturesEnum.COMPLEX.getAlias()) && Objects.equals(1, entity.getIsRedundant())) {
            return 1;
        } else if (!featureList.contains(FeaturesEnum.COMPLEX.getAlias()) && Objects.equals(1, entity.getIsRedundant())) {
            // 套餐下没有复杂字段
           return 0;
        }
        return 1;
    }

    /**
     * 判断是否有使用数据联动和关联其他表单的套餐
     * @param featureList
     * @param entity
     */
    public void setPackageLimit(List<String> featureList, FieldAttrEntity entity) {
        if (CollectionsUtil.isNotEmpty(featureList) && !featureList.contains(DefaultTypeEnum.DATARELY.getAlias()) || !featureList.contains(DefaultTypeEnum.LINKFORM.getAlias())) {
            if (!isCombo(entity.getFieldType()) && Objects.nonNull(entity.getDefaultAttr()) && Objects.equals(entity.getDefaultAttr().getDefaultType(), DefaultTypeEnum.DATARELY.getAlias())) {
                entity.setPackageLimit(1);
            } else if (isCombo(entity.getFieldType()) && Objects.equals(ComboTypeEnum.DATARELY.getType(), entity.getComboType())) {
                entity.setPackageLimit(1);
            } else if (isCombo(entity.getFieldType()) && Objects.equals(ComboTypeEnum.LINKFORM.getType(), entity.getComboType())) {
                entity.setPackageLimit(1);
            }
        }

    }

    /**
     * 判断是否是下拉框、单选按钮，复选按钮，下拉框复选
     * @param fieldType
     * @return ture ：是 false：否
     */
    public Boolean isCombo(Integer fieldType) {
        if (Objects.equals(FieldTypeEnum.COMBO.getType(), fieldType) || Objects.equals(FieldTypeEnum.COMBO_CHECK.getType(), fieldType)
                || Objects.equals(FieldTypeEnum.RADIO_GROUP.getType(), fieldType) || Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), fieldType)) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否有使用数据联动和关联其他表单的套餐
     * @param featureList
     * @param entity
     */
    public void limitFormula(List<String> featureList, FieldAttrEntity entity, Integer businessType) {
        if (!featureList.contains(DefaultTypeEnum.FORMULA.getAlias())) {
            String attr = entity.getAttr();
            if (StringUtil.isNotEmpty(entity.getParentAttr())) {
                attr = entity.getParentAttr() + StringConstant.POINT + entity.getAttr();
            }
            List<String> fieldList = SystemFieldFormulaEnum.getFieldList(businessType);
            if (Objects.nonNull(entity.getDefaultAttr())
                    && Objects.equals(entity.getDefaultAttr().getDefaultType(), DefaultTypeEnum.FORMULA.getAlias())
                    && CollectionsUtil.isNotEmpty(featureList) && !fieldList.contains(attr)) {
                entity.setPackageLimit(2);
            }
        }

    }

    /**
     * 主要是为了处理每个套餐具有的功能
     * @param corpid
     *
     */
    public List<String> getFeatureList(String corpid) throws XbbException {

        Integer feeType = getFeeType(corpid);
        if (!Objects.equals(PackageTypeEnum.ULTIMATE.getType(), feeType)) {
            Set<String> corpidSet = packageWhitelistHelp.getPackageWhitelist(corpid);
            if (corpidSet.contains(corpid)) {
                return FeaturesEnum.getFeatures();
            }
        }
        List<String> featureList = PackageVersionEnum.getFeatureList(feeType);
        return featureList;
    }

    /**
     * 套餐限制标识
     * @param chartIdList 套餐内的图表id
     * @param id 图表od
     * @param statisticsType 图表类型
     * @param num 已超出数量
     * @param featureList 功能类别
     * @return true:需要套餐限制 false：不用套餐限制
     */
    public boolean packageLimitFlag(List<Long> chartIdList, Long id, Integer statisticsType, Integer num, List<String> featureList) {
        // 非套餐内图表自定义图表，且该套餐超过限定数量
        boolean packageLimit = CollectionsUtil.isNotEmpty(chartIdList) &&  !chartIdList.contains(id)
                && Objects.equals(2, statisticsType) && num > 0;
        // 该套餐不包含自定义图表
        boolean isTrue = !featureList.contains(FeaturesEnum.BI_DATA_WAREHOUSE.getAlias()) && Objects.equals(2, statisticsType);
        return packageLimit || isTrue;
    }

    /**
     * 获取当前公司套餐不能看到的菜单alias集合
     * @param corpid
     * @return java.util.List<java.lang.String>
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public List<String> getUnSeeMenuList(String corpid) throws XbbException {
        BasePackageInfoVO basePackageInfoVO = getBasePackageInfoFromRedis(corpid);
        Integer feeType = basePackageInfoVO.getFeeType();
        //根据套餐获取当前公司套餐不能看到的菜单
        return VipSaasMenuEnum.getUnSeeMenuList(feeType);
    }

    /**
     * 获取当前公司套餐进销存不能看到的菜单alias集合
     * @param corpid
     * @return java.util.List<java.lang.String>
     * @throws XbbException
     * @author rsc
     * @since v1.0
     * @version v1.0
     */
    public List<String> getJxcUnSeeMenuList(String corpid) throws XbbException {
        BasePackageInfoVO basePackageInfoVO = getBasePackageInfoFromRedis(corpid);
        Integer feeType = basePackageInfoVO.getFeeType();
        //只有标准版做限制
        //根据套餐获取当前公司套餐不能看到的菜单
        if (Objects.equals(basePackageInfoVO.getFeeType(), PackageTypeEnum.STANDARD.getType())) {
            //获取公司创建时间
            CompanyEntity company = companyModel.getByKey(corpid);
            if (company != null) {
                if (company.getAddTime() > BasicConstant.JXC_ONLINE_DATE) {
                    return VipJxcSaasMenuEnum.getUnSeeMenuList(feeType);
                } else {
                    return VipJxcSaasMenuEnum.getOldCompanyUnSeeMenuList();
                }
            }
        }
        return new ArrayList<>();
    }

    /**
     * 获取当前公司套餐不能看到的表单code集合
     *
     * @param corpid 公司id
     * @return
     * @throws XbbException
     */
    public List<Integer> getUnSeeFormList(String corpid) throws XbbException {
        BasePackageInfoVO basePackageInfoVO = getBasePackageInfoFromRedis(corpid);
        Integer feeType = basePackageInfoVO.getFeeType();
        //根据套餐获取当前公司套餐不能看到的菜单
        return VipSaasMenuEnum.getUnSeeFormList(feeType);
    }

    /**
     * 获取基础套餐到缓存（为最基础的方法）
     * @param corpid
     * @return
     * @throws XbbException
     * 创建时间 2019/4/9 2:37 PM
     * 修改时间 2019/4/9 2:37 PM
     * @author chy
     * @since v1.0
     * @version v1.0
     */
    public BasePackageInfoVO getBasePackageInfoFromRedis(String corpid) throws XbbException {

        String basePackageStr = paasRedisHelper.getValue(RedisPrefixConstant.BASE_PACKAGE, corpid);
        if (!StringUtil.isEmpty(basePackageStr)) {
            return JSON.parseObject(basePackageStr, BasePackageInfoVO.class);
        }
        CompanyEntity company = companyModel.getByKey(corpid);
        if (company == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100011);
        }
        feeCompanyModel.setFeeCompanyInfo4Company(company);
        BasePackageInfoVO basePackageInfoVO = getPackageInfoFromCompany(company);
        // 获取免费套餐数量
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("isPay", BasicConstant.ZERO);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        Integer feeNum = feeCompanyModel.getEntitysCount(param);
        basePackageInfoVO.setFeeNum(feeNum);
        paasRedisHelper.setValue(RedisPrefixConstant.BASE_PACKAGE, corpid, basePackageInfoVO, RedisTimeConstant.TEN_MINUTES);
        return basePackageInfoVO;
    }

    /**
     * 从redis获取公司开通时间（时间点前的返回true）
     * @param corpid
     * @return
     * @throws XbbException
     */
    public boolean getCompanyAddTimeFlag(String corpid) throws XbbException {
        String basePackageStr = paasRedisHelper.getValue(RedisPrefixConstant.BASE_COMPANY_INFO, corpid);
        if (!StringUtil.isEmpty(basePackageStr)) {
            if(Objects.equals("1",basePackageStr)){
                return true;
            }
            return false;
        }
        CompanyEntity company = companyModel.getByKey(corpid);
        if (company == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100011);
        }
        boolean flag = false;
        int flagNum = 0;
        //1650556800  2022-04-22 00:00:00  新注册的公司直接走CK
        if (company.getAddTime() < 1650556800) {
            flagNum = 1;
            flag = true;
        }
        paasRedisHelper.setValue(RedisPrefixConstant.BASE_COMPANY_INFO, corpid, flagNum, RedisConstant.LONG_DURATION);
        return flag;
    }

    /**
     * 获取公司中的套餐信息
     * @param company
     * 创建时间 2019/6/28 10:10 AM
     * 修改时间 2019/6/28 10:10 AM
     * @author chy
     * @since v1.0
     * @version v1.0
     */
    private BasePackageInfoVO getPackageInfoFromCompany(CompanyEntity company) {
        BasePackageInfoVO basePackageInfoVO = new BasePackageInfoVO();
        basePackageInfoVO.setCorpName(company.getCorpName());
        basePackageInfoVO.setFeeEndTime(company.getFeeEndTime());
        basePackageInfoVO.setFeeName(company.getFeeName());
        basePackageInfoVO.setFeeStartTime(company.getFeeStartTime());
        basePackageInfoVO.setFeeType(company.getFeeType());
        basePackageInfoVO.setFeeUserNum(company.getFeeUserNum());
        basePackageInfoVO.setOrderType(company.getOrderType());
        basePackageInfoVO.setVipNum(company.getVipNum());
        // 是否为免费套餐：0收费，1免费
        basePackageInfoVO.setIsFree(company.getIsFree());
        //1.试用，0.非试用
        basePackageInfoVO.setIsTrail(StringUtil.isNotEmpty(company.getMainCorpid()) && Objects.equals(company.getIsFree(),1)?1:0);
        basePackageInfoVO.setMainCorpid(company.getMainCorpid());
        basePackageInfoVO.setScale(company.getScale());
        basePackageInfoVO.setIndustry(company.getIndustry());
        basePackageInfoVO.setUserNum(company.getUserNum());
        return basePackageInfoVO;
    }

    /**
     * 获取版本
     * @param corpid
     * @return BasePackageInfoVO
     * @throws XbbException
     */
    public Integer getFeeType(String corpid) throws XbbException {
        BasePackageInfoVO basePackageInfoVO = getBasePackageInfoFromRedis(corpid);
        return basePackageInfoVO.getFeeType();
    }

    /**
     * 判断该公司的套餐类型是否是“标准版”
     * @param corpid
     * @return
     */
    public Boolean isStandardWithFeeType(String corpid) throws XbbException {
        Integer feeType = getFeeType(corpid);
        return Objects.equals(feeType, PackageTypeEnum.STANDARD.getType());
    }

    /**
     * 判断该公司套餐是否为"旗舰版"
     * @param corpid
     * @return true：是旗舰版
     *         false：不是旗舰版
     * @throws XbbException
     */
    public Boolean isUltimateWithFeeType(String corpid) throws XbbException {
        Integer feeType = getFeeType(corpid);
        return Objects.equals(feeType, PackageTypeEnum.ULTIMATE.getType());
    }

    /**
     * 校验公司是否有高级图表的使用权限
     *
     * @param corpid
     * @return boolean
     * @author zyy
     * @date 2022/4/18
     * @version v1.0
     */
    public boolean checkSeniorChartPower(String corpid) throws XbbException{
        //该版本旗舰版有权限，高级版没有权限，后续高级图表套餐确认之后，该方法要进行重构
        Integer feeType = getFeeType(corpid);
        return Objects.equals(PackageTypeEnum.ULTIMATE.getType(), feeType);
    }

    /**
     * 公司套餐的可见图表验证
     *
     * @param isAdmin 是否为管理员
     * @param chartEntityEtx  图表详情
     * @param chartIdList  套餐数量内的图表id数组
     * @param num  图表数量，小于0则未超过套餐可用数量
     * @param featureList  套餐功能数组
     * @return java.lang.String  无限制为""
     * @author zyy
     * @date 2022/5/5
     * @version v1.0
     */
    public void companyPackageVerify(boolean isAdmin, ChartEntityEtx chartEntityEtx, List<Long> chartIdList, Integer num, List<String> featureList) throws XbbException {
        String limitMsg = "";
        List<ChartTypeEnum> seniorChartList = ChartTypeEnum.getSeniorChartList();
        if (packageLimitFlag(chartIdList, chartEntityEtx.getId(), chartEntityEtx.getStatisticsType(), num, featureList)){
            //超出套餐数量
            limitMsg = I18nMessageUtil.getMessage(PackageConstant.CUSTOM_CHART_PACKAGE_LIMIT_MESSAGE);
        }else if(!Objects.equals(PackageTypeEnum.ULTIMATE.getType(), getFeeType(chartEntityEtx.getCorpid()))){
            if(seniorChartList.contains(ChartTypeEnum.getByCode(chartEntityEtx.getChartType()))){
                //无权限查看高级图表类型
                limitMsg = I18nMessageUtil.getMessage(PackageConstant.CUSTOM_ADVANCED_CHART_PACKAGE_LIMIT_MESSAGE);
            }else if(ChartSourceEnum.isDataSet(chartEntityEtx.getSingle())){
                //无权限使用数据集
                limitMsg = I18nMessageUtil.getMessage(PackageConstant.CUSTOM_DATASET_CHART_PACKAGE_LIMIT_MESSAGE);
            }
        }
        if(StringUtils.isNotBlank(limitMsg)){
            chartEntityEtx.setPackageLimit(1);
            chartEntityEtx.setPackageLimitMsg(limitMsg);
            if(isAdmin) {
                chartEntityEtx.setUpgrade(1);
            }
        }
    }
}
